﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using MMOEng.Packets;
using MMOEng.Packets.EnginePackets;

using RakNet;
using System.IO;
using MMOEng.Managers;

namespace MMOShardServer
{
    public class Network
    {
        private RakPeerInterface interfaceRak;
        private Packet packet;

        BitStream receiveBS;
        BitStream writeBS;

        string serverAddress;
        ushort serverPort;

        bool isConnected;

        private static readonly ushort MAX_CLIENTS = 1024;

        private static readonly SystemAddress UnassignedAddress = new SystemAddress(0xFFFFFFFF, 0xFFFF);

        public Network(string sa,ushort sp)
        {
            serverAddress = sa;
            serverPort = sp;

            if (!File.Exists("RakNet.dll"))
            {
                System.Console.WriteLine("Missing RakNet library file!");
                return;
            }

            isConnected = true;//false;


            receiveBS = new BitStream();
            writeBS = new BitStream();

            try
            {
                interfaceRak = RakPeer.GetInstance();
                interfaceRak.Startup(MAX_CLIENTS, new SocketDescriptor(serverPort, serverAddress), 1);
                interfaceRak.SetMaximumIncomingConnections(MAX_CLIENTS);
            }
            catch (Exception e)
            {
                System.Console.WriteLine(e.Message);
                isConnected = false;
            }
        }

        public bool IsConnected() { return isConnected; }

        ~Network()
        {
            //cleanup
            RakPeer.DestroyInstance(interfaceRak);
        }

        public void Update()
        {
            packet = interfaceRak.Receive();
            if (packet != null)
            {
                //process received packet

                //predefined types
                switch (packet.data[0])
                {
                    case (byte)DefaultMessageIDTypes.ID_CONNECTION_REQUEST_ACCEPTED:
                        isConnected = true;
                        Console.WriteLine("= We connected, not really sure why? Especially because we are the server!");
                        break;
                    case (byte)DefaultMessageIDTypes.ID_NEW_INCOMING_CONNECTION:
                        Console.WriteLine("= A new client connected from {0}",packet.systemAddress.ToString());
                        break;
                    default:
                        Console.WriteLine("= packetId: "+packet.data[0]);
                        break;
                }

                //registered types
                if (packet.data[0] > (byte)DefaultMessageIDTypes.ID_USER_PACKET_ENUM)
                {
                    ReadPacket(packet, packet.data[0]);
                }
            }

            interfaceRak.DeallocatePacket(packet);
            //Engine is single threaded so drawing should incur a large enough pause
            //System.Threading.Thread.Sleep(50);    
        }

        private void ReadPacket(Packet packet, byte type)
        {
            /*receiveBS.Reset();
            receiveBS.Write(packet.data, packet.length);
            receiveBS.IgnoreBytes(1);*/

            //resend to all connected clients(
            writeBS.Reset();
            writeBS.Write((byte)PacketType.P_DELTAU);
            writeBS.Write(packet.data, packet.length);
            interfaceRak.Send(writeBS, PacketPriority.HIGH_PRIORITY, PacketReliability.RELIABLE_ORDERED, (char)0, UnassignedAddress, true);
        }
    }
}
